package com.dsl.benchmark;

import com.dsl.perfs.ExprEvalutorHelper;
import com.dsl.perfs.GroovyShellUtils;
import org.openjdk.jmh.annotations.*;
import org.openjdk.jmh.infra.Blackhole;
import org.openjdk.jmh.runner.Runner;
import org.openjdk.jmh.runner.RunnerException;
import org.openjdk.jmh.runner.options.Options;
import org.openjdk.jmh.runner.options.OptionsBuilder;

import java.util.Map;
import java.util.Random;
import java.util.TreeMap;
import java.util.concurrent.TimeUnit;

/**
 * 表达式基准测试(antlr和groovy多个布尔条件测试)
 *
 * @author evoup
 */
@SuppressWarnings("Duplicates")
@BenchmarkMode(Mode.AverageTime)
@OutputTimeUnit(TimeUnit.MILLISECONDS)
@State(Scope.Benchmark)
@Fork(value = 2, jvmArgs = {"-Xms4G", "-Xmx4G"})
// 默认Warmup和Measurement都是5
// @Warmup(iterations = 3)
// @Measurement(iterations = 8)
public class BenchmarkExpressionNBoolean {
    @Param({"10000000"})
    private int N;

    private String boolexpr1 = "1 && 2";
    private String boolexpr2 = "1 && 2 || 3";
    private String boolexpr3 = "1 && 2 || 3 || 4";
    private String boolexpr4 = "1 && 2 || 3 || 4 && 5";
    private String boolexpr5 = "1 && 2 || 3 || 4 && 5 || 6";

    public static void main(String[] args) throws RunnerException {
        // https://stackoverflow.com/questions/24928922/jmh-what-does-the-score-value-mean
        Options opt = new OptionsBuilder()
            .include(BenchmarkExpressionNBoolean.class.getSimpleName())
            .forks(1).threads(1).build();
        new Runner(opt).run();
    }

    @Benchmark
    public void antlrB1(Blackhole bh) {
        long randomSeed = 10001L;
        Random random = new Random(randomSeed);
        random.setSeed(randomSeed);
        for (int i = 0; i <= N; i++) {
            Map<String, Boolean> params = new TreeMap<>();
            params.put("1", random.nextBoolean());
            params.put("2", random.nextBoolean());
            bh.consume(ExprEvalutorHelper.exec(boolexpr1, params));
            i++;
        }
    }

    @Benchmark
    public void antlrB2(Blackhole bh) {
        long randomSeed = 10001L;
        Random random = new Random(randomSeed);
        random.setSeed(randomSeed);
        for (int i = 0; i <= N; i++) {
            Map<String, Boolean> params = new TreeMap<>();
            params.put("1", random.nextBoolean());
            params.put("2", random.nextBoolean());
            params.put("3", random.nextBoolean());
            bh.consume(ExprEvalutorHelper.exec(boolexpr2, params));
            i++;
        }
    }

    @Benchmark
    public void antlrB3(Blackhole bh) {
        long randomSeed = 10001L;
        Random random = new Random(randomSeed);
        random.setSeed(randomSeed);
        for (int i = 0; i <= N; i++) {
            Map<String, Boolean> params = new TreeMap<>();
            params.put("1", random.nextBoolean());
            params.put("2", random.nextBoolean());
            params.put("3", random.nextBoolean());
            params.put("4", random.nextBoolean());
            bh.consume(ExprEvalutorHelper.exec(boolexpr3, params));
            i++;
        }
    }

    @Benchmark
    public void antlrB4(Blackhole bh) {
        long randomSeed = 10001L;
        Random random = new Random(randomSeed);
        random.setSeed(randomSeed);
        for (int i = 0; i <= N; i++) {
            Map<String, Boolean> params = new TreeMap<>();
            params.put("1", random.nextBoolean());
            params.put("2", random.nextBoolean());
            params.put("3", random.nextBoolean());
            params.put("4", random.nextBoolean());
            params.put("5", random.nextBoolean());
            bh.consume(ExprEvalutorHelper.exec(boolexpr4, params));
            i++;
        }
    }

    @Benchmark
    public void antlrB5(Blackhole bh) {
        long randomSeed = 10001L;
        Random random = new Random(randomSeed);
        random.setSeed(randomSeed);
        for (int i = 0; i <= N; i++) {
            Map<String, Boolean> params = new TreeMap<>();
            params.put("1", random.nextBoolean());
            params.put("2", random.nextBoolean());
            params.put("3", random.nextBoolean());
            params.put("4", random.nextBoolean());
            params.put("5", random.nextBoolean());
            params.put("6", random.nextBoolean());
            bh.consume(ExprEvalutorHelper.exec(boolexpr5, params));
            i++;
        }
    }

    @Benchmark
    public void groovyB1(Blackhole bh) {
        String nboolExpr = boolexpr1;
        nboolExpr = nboolExpr.replace("1", "t1");
        nboolExpr = nboolExpr.replace("2", "t2");
        long randomSeed = 10001L;
        Random random = new Random(randomSeed);
        random.setSeed(randomSeed);
        for (int i = 0; i <= N; i++) {
            Map<String, Object> params = new TreeMap<>();
            params.put("t1", random.nextBoolean());
            params.put("t2", random.nextBoolean());
            bh.consume(GroovyShellUtils.execExpr(nboolExpr, params, Boolean.class));
            i++;
        }
    }

    @Benchmark
    public void groovyB2(Blackhole bh) {
        String nboolExpr = boolexpr1;
        nboolExpr = nboolExpr.replace("1", "t1");
        nboolExpr = nboolExpr.replace("2", "t2");
        nboolExpr = nboolExpr.replace("3", "t3");
        long randomSeed = 10001L;
        Random random = new Random(randomSeed);
        random.setSeed(randomSeed);
        for (int i = 0; i <= N; i++) {
            Map<String, Object> params = new TreeMap<>();
            params.put("t1", random.nextBoolean());
            params.put("t2", random.nextBoolean());
            params.put("t3", random.nextBoolean());
            bh.consume(GroovyShellUtils.execExpr(nboolExpr, params, Boolean.class));
            i++;
        }
    }

    @Benchmark
    public void groovyB3(Blackhole bh) {
        String nboolExpr = boolexpr1;
        nboolExpr = nboolExpr.replace("1", "t1");
        nboolExpr = nboolExpr.replace("2", "t2");
        nboolExpr = nboolExpr.replace("3", "t3");
        nboolExpr = nboolExpr.replace("4", "t4");
        long randomSeed = 10001L;
        Random random = new Random(randomSeed);
        random.setSeed(randomSeed);
        for (int i = 0; i <= N; i++) {
            Map<String, Object> params = new TreeMap<>();
            params.put("t1", random.nextBoolean());
            params.put("t2", random.nextBoolean());
            params.put("t3", random.nextBoolean());
            params.put("t4", random.nextBoolean());
            bh.consume(GroovyShellUtils.execExpr(nboolExpr, params, Boolean.class));
            i++;
        }
    }

    @Benchmark
    public void groovyB4(Blackhole bh) {
        String nboolExpr = boolexpr1;
        nboolExpr = nboolExpr.replace("1", "t1");
        nboolExpr = nboolExpr.replace("2", "t2");
        nboolExpr = nboolExpr.replace("3", "t3");
        nboolExpr = nboolExpr.replace("4", "t4");
        nboolExpr = nboolExpr.replace("5", "t5");
        long randomSeed = 10001L;
        Random random = new Random(randomSeed);
        random.setSeed(randomSeed);
        for (int i = 0; i <= N; i++) {
            Map<String, Object> params = new TreeMap<>();
            params.put("t1", random.nextBoolean());
            params.put("t2", random.nextBoolean());
            params.put("t3", random.nextBoolean());
            params.put("t4", random.nextBoolean());
            params.put("t5", random.nextBoolean());
            bh.consume(GroovyShellUtils.execExpr(nboolExpr, params, Boolean.class));
            i++;
        }
    }

    @Benchmark
    public void groovyB5(Blackhole bh) {
        String nboolExpr = boolexpr1;
        nboolExpr = nboolExpr.replace("1", "t1");
        nboolExpr = nboolExpr.replace("2", "t2");
        nboolExpr = nboolExpr.replace("3", "t3");
        nboolExpr = nboolExpr.replace("4", "t4");
        nboolExpr = nboolExpr.replace("5", "t5");
        nboolExpr = nboolExpr.replace("6", "t6");
        long randomSeed = 10001L;
        Random random = new Random(randomSeed);
        random.setSeed(randomSeed);
        for (int i = 0; i <= N; i++) {
            Map<String, Object> params = new TreeMap<>();
            params.put("t1", random.nextBoolean());
            params.put("t2", random.nextBoolean());
            params.put("t3", random.nextBoolean());
            params.put("t4", random.nextBoolean());
            params.put("t5", random.nextBoolean());
            params.put("t6", random.nextBoolean());
            bh.consume(GroovyShellUtils.execExpr(nboolExpr, params, Boolean.class));
            i++;
        }
    }
}
